// g++ dtls_tools.cpp dtls_tools_server.cpp -o dtls_tools_server -I ./ -L ./ -lssl -lcrypto -lpthread -ldl

#include "dtls_tools.hpp"


int main() {
  int sock = CreateSocket(SERVER_PORT);
  /* startup SSL */
  krx_begin();
 
  /* create server objects */
  krx server;
 
  /* init server. */
  if(krx_ssl_ctx_init(&server, "server") < 0) {
    exit(EXIT_FAILURE);
  }
  if(krx_ssl_init(&server, 1, krx_ssl_server_info_callback) < 0) {
    exit(EXIT_FAILURE);
  }
 
  printf("+ Initialized server.\n");

  char replybuf[MAX_PACKAGE_LEN];
  int replylen = 0;

  char outbuf[MAX_PACKAGE_LEN];
  struct sockaddr_in cliaddr;
  socklen_t cliaddr_len = sizeof(cliaddr);

  while(true) {
    // recvfrom a client
      int n = recvfrom(sock, (char *)&outbuf, MAX_PACKAGE_LEN, 0, (struct sockaddr *)&cliaddr, &cliaddr_len);
      if (n < 0) {
          perror("Unable to recvfrom");
          exit(EXIT_FAILURE);
      }
      printf("recvfrom ok,n=%d,addr=%s:%u!\n",n,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
      //print_dump((unsigned char*)outbuf, n);

      if (ProcessOnDtls(outbuf, n, &server, replybuf, replylen))
      {
        printf("ProcessOnDtls error\n");
        break;
      }
      printf("ProcessOnDtls ok! replylen=%d\n", replylen);
      //print_dump((unsigned char*)replybuf, replylen);
      if (replylen)
      {
        int n = sendto(sock, replybuf, replylen, 0, (struct sockaddr*)&cliaddr,sizeof(cliaddr));
        printf("sendto,n=%d,addr=%s:%u!\n",n,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
      }
      if (SSL_is_init_finished(server.ssl))
      {
        printf("connected!\n");
        break;
      }
  }

  /* encrypt some data and send it to the client */
  char buf[521] = { 0 } ;
  sprintf(buf, "%s", "Hello world");
  int buflen = SSL_write(server.ssl, buf, sizeof(buf));

  krx_ssl_handle_traffic_read(&server, replybuf, replylen);
  printf("krx_ssl_handle_traffic_read ok! replylen=%d\n", replylen);
  //print_dump((unsigned char*)replybuf, replylen);
  if (replylen)
  {
    int n = sendto(sock, replybuf, replylen, 0, (struct sockaddr*)&cliaddr,sizeof(cliaddr));
    printf("sendto,n=%d,addr=%s:%u!\n",n,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
  }

  krx_ssl_shutdown(&server);
 
  //krx_end();
  close(sock);
  return EXIT_SUCCESS;
}
 